#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2025/10/25 0:00
# @Author  : summer
# @Email   : 610658552@qq.com
# @File    : util_dingtalk.py
# @Software: PyCharm
# @Desc    :
import requests
import json
import time
import hmac
import hashlib
import base64
import urllib.parse
from sdingding.models import DingTalkConfig


class DingTalkSender:
    """钉钉机器人消息发送工具（完整支持所有消息类型）"""

    def __init__(self, access_token, secret):
        self.obj = DingTalkConfig.objects.first()
        self.prex_url = "https://oapi.dingtalk.com/robot/send?access_token="
        self.webhook_url = f"{self.prex_url}{self.obj.access_token}" if not access_token else access_token
        self.secret = DingTalkConfig.objects.first().secret
        self.secret = self.secret if not secret else secret

    def _generate_signature(self):
        """生成安全签名"""
        if not self.secret:
            return {}

        timestamp = str(round(time.time() * 1000))
        sign = hmac.new(
            self.secret.encode('utf-8'),
            f"{timestamp}\n{self.secret}".encode('utf-8'),
            digestmod=hashlib.sha256
        ).digest()
        return {
            "timestamp": timestamp,
            "sign": urllib.parse.quote_plus(base64.b64encode(sign))
        }

    def send_text(self, content, at_mobiles=None, at_all=False):
        """发送文本消息"""
        payload = {
            "msgtype": "text",
            "text": {"content": content},
            "at": {
                "atMobiles": at_mobiles or [],
                "isAtAll": at_all
            }
        }
        return self._send(payload)

    def send_markdown(self, title, text, at_mobiles=None, at_all=False):
        """发送Markdown格式消息"""
        payload = {
            "msgtype": "markdown",
            "markdown": {"title": title, "text": text},
            "at": {
                "atMobiles": at_mobiles or [],
                "isAtAll": at_all
            }
        }
        return self._send(payload)

    def send_link(self, title, text, message_url, pic_url=""):
        """发送链接消息"""
        payload = {
            "msgtype": "link",
            "link": {
                "title": title,
                "text": text,
                "messageUrl": message_url,
                "picUrl": pic_url
            }
        }
        return self._send(payload)

    def send_single_action_card(self, title, text, button_title, button_url, btn_vertical=False):
        """发送单按钮交互卡片"""
        payload = {
            "msgtype": "actionCard",
            "actionCard": {
                "title": title,
                "text": text,
                "singleTitle": button_title,
                "singleURL": button_url,
                "btnOrientation": 1 if btn_vertical else 0
            }
        }
        return self._send(payload)

    def send_multi_action_card(self, title, text, buttons, btn_vertical=False):
        """发送多按钮交互卡片"""
        payload = {
            "msgtype": "actionCard",
            "actionCard": {
                "title": title,
                "text": text,
                "btns": buttons,
                "btnOrientation": 1 if btn_vertical else 0
            }
        }
        return self._send(payload)

    def send_feed_card(self, links):
        """发送聚合链接消息"""
        payload = {
            "msgtype": "feedCard",
            "feedCard": {"links": links}
        }
        return self._send(payload)

    def _send(self, payload):
        """统一发送请求"""
        try:
            params = self._generate_signature()
            response = requests.post(
                self.webhook_url,
                params=params,
                headers={"Content-Type": "application/json"},
                data=json.dumps(payload),
                timeout=5
            )
            result = response.json()

            if result.get("errcode") != 0:
                raise Exception(result.get("errmsg", "发送失败"))
            return result

        except Exception as e:
            raise Exception(f"钉钉消息发送异常: {str(e)}")


# --------------------- 使用示例 ---------------------
if __name__ == "__main__":
    # 初始化机器人
    bot = DingTalkSender()

    # 发送文本消息
    bot.send_text("服务器异常告警", at_mobiles=["13800138000"])

    # 发送带格式的消息
    bot.send_markdown(
        title="项目更新",
        text="### 新版本发布\n- 版本: v2.0\n- 更新内容: 优化系统性能"
    )

    # 发送带按钮的卡片
    bot.send_multi_action_card(
        title="审批通知",
        text="请审批以下请求",
        buttons=[
            {"title": "同意", "actionURL": "https://example.com/approve"},
            {"title": "拒绝", "actionURL": "https://example.com/reject"}
        ]
    )
